using System;
using System.Linq;
using System.Linq.Expressions;
using L2NH.Core.Domain;
using NHibernate;
using NHibernate.Linq;

namespace L2NH.Infrastructure.DataAccess
{
   public interface IRepository_Linqified
   {
      T Load<T>(int id) where T : Entity;
      T Get<T>(int id) where T : Entity;
      T Get<T>(Expression<Func<T, bool>> prediate) where T : Entity;

      IQueryable<T> FindAll<T>() where T : Entity;
      IQueryable<T> Find<T>(Expression<Func<T, bool>> prediate) where T : Entity;

      void Add<T>(T entity) where T : Entity;
      void Remove<T>(T entity) where T : Entity;

      void SubmitChanges();
   }

   public class NHRepository_Linqified : IRepository_Linqified
   {
      public NHRepository_Linqified()
      {
         _session = UnitOfWork.CurrentSession;
      }

      private readonly ISession _session;

      public T Load<T>(int id) where T : Entity
      {
         return _session.Load<T>(id);
      }
      public T Get<T>(int id) where T : Entity
      {
         return _session.Get<T>(id);
      }
      public T Get<T>(Expression<Func<T, bool>> predicate) where T : Entity
      {
         return _session.Linq<T>().SingleOrDefault(predicate);
      }

      public IQueryable<T> FindAll<T>() where T : Entity
      {
         return _session.Linq<T>();
      }
      public IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : Entity
      {
         return _session.Linq<T>().Where(predicate);
      }

      public void Add<T>(T entity) where T : Entity
      {
         _session.Save(entity);
      }

      public void Remove<T>(T entity) where T : Entity
      {
         _session.Delete(entity);
      }

      public void SubmitChanges()
      {
         try
         {
            _session.Transaction.Commit();
            _session.BeginTransaction();
         }
         catch
         {
            _session.Transaction.Rollback();
            throw;
         }
      }
   }
}